package br.utfpr.edu.managedBean;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;

import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;

import br.utfpr.edu.bean.Blast;
import br.utfpr.edu.bean.Gene;
import br.utfpr.edu.business.NegocioException;
import br.utfpr.edu.dao.BlastDao;
import br.utfpr.edu.dao.GeneDao;
import br.utfpr.edu.interfaces.IBlast;
import br.utfpr.edu.utility.CriaArquivo;


@SuppressWarnings("serial")
@ManagedBean(name = "blastFrm")
@SessionScoped
public class BlastFrm extends ListaDetalhe<IBlast>{
	
	private final String caminho;
	private final String FASTA = "arquivosFasta";
	private UploadedFile arquivoFasta;
	private IBlast blast;
	private String caminhoFasta;
	private List<Blast> colecaoBlast;
	private String bancoSelecionado;
	private SelectItem[] arquivosFasta;
	private String arquivoFastaSelecionado;
	private String sequenciaFasta;
	private File arquivoFastaPadrao;
	private CriaArquivo criaArquivo;
	private boolean gapOpen;
	private boolean gapExtends; 
	private boolean evalue;
	private boolean opcaoW;
	private float valorEvalue;
	private int valorWordSize;
	private Map<String,String> bancosBlast = new HashMap<String, String>();  
	
	public BlastFrm(){
		blast = new BlastDao();
		colecaoBlast = new ArrayList<Blast>();
		caminho = getContextPath()+FASTA;
	}
	
	
	public void fastaFileUpload(FileUploadEvent event) throws IOException {
		arquivoFasta  = event.getFile();
  //      FacesMessage msg = new FacesMessage("Successo ", event.getFile().getFileName() + " foi carregado.");  
   //     FacesContext.getCurrentInstance().addMessage("teste", msg);
		System.out.println(arquivoFasta.getFileName());
        caminhoFasta = caminho + "\\" + event.getFile().getFileName();  
  
        byte[] conteudo = event.getFile().getContents();  
        FileOutputStream fos = new FileOutputStream(caminhoFasta);  
        fos.write(conteudo);  
        fos.close();  
	}
	
	/*
	public void fastaFileUpload(FileUploadEvent event) {
		arquivoFasta = event.getFile();
    }*/

	public void enter(){
		limpar();
		carregar();
		try {
			FacesContext.getCurrentInstance().getExternalContext().redirect("../blast/blast.faces");
		} catch (IOException e) {
			
		}
	}
	
	//Modificar para ser usado em uma unica classe e ser chamado nas demais
		public void carregar(){
			try {
				List<Gene> colecaoFasta;
				colecaoFasta  = new GeneDao().pesquisar();
				arquivosFasta = new SelectItem[colecaoFasta.size()];
				for(int i = 0; i<colecaoFasta.size(); i++){
					arquivosFasta[i] = new SelectItem(colecaoFasta.get(i).getId(),
							colecaoFasta.get(i).getName());
				}
			} catch (NegocioException e) {
				imprimirErrosPagina(e);
			}
		}
	
	private void limpar(){
		arquivoFasta = null;
		caminhoFasta = "";
		bancoSelecionado = "";
		colecaoBlast.clear();
		valorEvalue = 0;
		valorWordSize = 0;
		gapOpen = false;
		gapExtends = false; 
		evalue = false;
		opcaoW = false;
	}
	
	public void executeBlast() throws NegocioException{
		try {
			colecaoBlast.clear();
			if(arquivoFasta == null){
				System.out.println(sequenciaFasta);
				try {
					criarArquivoFasta(sequenciaFasta);
					colecaoBlast = blast.executeBlast(caminho+"/"+fileName()+".fasta",caminho+"/arquivoFastaCriado.fasta", caminho, 
							gapOpen, gapExtends, evalue, opcaoW, valorWordSize, valorEvalue);
					imprimirSucessoPagina();//(query, subject, caminhoXml, gapOpen, gapExtend, evalue, word, valorWord, valorEvalue)
				} catch (IOException e) {
					imprimirErrosPagina(e.getMessage());
					throw new NegocioException();
				}
			}else{
				//colecaoBlast = blast.executeBlastXml(caminho+"/"+fileName()+".fasta", caminho+"/"+arquivoFasta.getFileName(),caminho);
				colecaoBlast = blast.executeBlast(caminho+"/"+fileName()+".fasta",caminho+"/"+arquivoFasta.getFileName(), caminho, 
						gapOpen, gapExtends, evalue, opcaoW, valorWordSize, valorEvalue);
				imprimirSucessoPagina();
			}	
		} catch (NegocioException e) {
			imprimirErrosPagina(e);
		} catch (FileNotFoundException e) {
			imprimirErrosPagina(e.getMessage());
		}
	}
	
	
	private void criarArquivoFasta(String sequenciaFasta) throws IOException {
		arquivoFastaPadrao = new File(caminho+"/arquivoFastaCriado.fasta");
        if (arquivoFastaPadrao.exists()) {
        	arquivoFastaPadrao.delete();
       } else {
    	   arquivoFastaPadrao.createNewFile();
       }
        
        FileOutputStream fos = new FileOutputStream(arquivoFastaPadrao);
        fos.write(sequenciaFasta.getBytes());
        fos.close();
        //escritor = criaArquivo.CriaEscritorBinario(arquivoFastaPadrao);
        //criaArquivo.EscreveObjeto(escritor, sequenciaFasta, false);
	}


	/**
	 * 
	 * @return o nome do arquivo fasta selecionado na combo
	 */
	private String fileName(){
		SelectItem fastaSelecionado = null; 
		for(int i =0; i< arquivosFasta.length; i++){
			if(String.valueOf(arquivosFasta[i].getValue()).equals(arquivoFastaSelecionado)){
				fastaSelecionado = arquivosFasta[i];
				break;
			}
		}
		return fastaSelecionado.getValue()+"-"+fastaSelecionado.getLabel();
	}

	@Override
	public void sort(String column, boolean ascending) {
		// TODO Auto-generated method stub
		
	}

	public UploadedFile getArquivoFasta() {
		return arquivoFasta;
	}

	public void setArquivoFasta(UploadedFile arquivoFasta) {
		this.arquivoFasta = arquivoFasta;
	}

	public String getCaminhoFasta() {
		return caminhoFasta;
	}


	public IBlast getBlast() {
		return blast;
	}


	public void setBlast(IBlast blast) {
		this.blast = blast;
	}


	public String getCaminho() {
		return caminho;
	}


	public void setCaminhoFasta(String caminhoFasta) {
		this.caminhoFasta = caminhoFasta;
	}


	public List<Blast> getColecaoBlast() {
		return colecaoBlast;
	}


	public void setColecaoBlast(List<Blast> colecaoBlast) {
		this.colecaoBlast = colecaoBlast;
	}


	public Map<String,String> getBancosBlast() {
		return bancosBlast;
	}


	public void setBancosBlast(Map<String,String> bancosBlast) {
		this.bancosBlast = bancosBlast;
	}


	public String getBancoSelecionado() {
		return bancoSelecionado;
	}


	public void setBancoSelecionado(String bancoSelecionado) {
		this.bancoSelecionado = bancoSelecionado;
	}


	public SelectItem[] getArquivosFasta() {
		return arquivosFasta;
	}


	public void setArquivosFasta(SelectItem[] arquivosFasta) {
		this.arquivosFasta = arquivosFasta;
	}


	public String getArquivoFastaSelecionado() {
		return arquivoFastaSelecionado;
	}


	public void setArquivoFastaSelecionado(String arquivoFastaSelecionado) {
		this.arquivoFastaSelecionado = arquivoFastaSelecionado;
	}


	public String getSequenciaFasta() {
		return sequenciaFasta;
	}


	public void setSequenciaFasta(String sequenciaFasta) {
		this.sequenciaFasta = sequenciaFasta;
	}

	public File getArquivoFastaPadrao() {
		return arquivoFastaPadrao;
	}

	public void setArquivoFastaPadrao(File arquivoFastaPadrao) {
		this.arquivoFastaPadrao = arquivoFastaPadrao;
	}

	public CriaArquivo getCriaArquivo() {
		return criaArquivo;
	}

	public void setCriaArquivo(CriaArquivo criaArquivo) {
		this.criaArquivo = criaArquivo;
	}

	public boolean isGapOpen() {
		return gapOpen;
	}

	public void setGapOpen(boolean gapOpen) {
		this.gapOpen = gapOpen;
	}

	public boolean isGapExtends() {
		return gapExtends;
	}

	public void setGapExtends(boolean gapExtends) {
		this.gapExtends = gapExtends;
	}

	public boolean isEvalue() {
		return evalue;
	}

	public void setEvalue(boolean evalue) {
		this.evalue = evalue;
	}

	public boolean isOpcaoW() {
		return opcaoW;
	}

	public void setOpcaoW(boolean opcaoW) {
		this.opcaoW = opcaoW;
	}

	public float getValorEvalue() {
		return valorEvalue;
	}

	public void setValorEvalue(float valorEvalue) {
		this.valorEvalue = valorEvalue;
	}

	public int getValorWordSize() {
		return valorWordSize;
	}

	public void setValorWordSize(int valorWordSize) {
		this.valorWordSize = valorWordSize;
	}

	
}
